package com.taplinker.client.core;

import java.io.File;
import java.lang.ref.WeakReference;
import java.net.URL;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map.Entry;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;

import com.taplinker.client.AppConfigContext;
import com.taplinker.client.widget.LoadImageView;
import com.taplinker.core.cache.CacheOutException;
import com.taplinker.core.cache.MemCacheImpl;
import com.taplinker.core.rpc.Result;
import com.taplinker.core.rpc.command.SimpleBaseCommand;
import com.taplinker.core.rpc.http.HttpTemplate;
import com.taplinker.core.rpc.http.client.cache.CacheKey;
import com.taplinker.core.rpc.http.client.cache.HttpCacheDAO;
import com.taplinker.core.rpc.http.client.cache.HttpCacheItem;
import com.taplinker.core.util.LogUtil;

public class ImageManager{
	private MemCacheImpl memCache;
	private static ImageManager instance;
	
	private ImageManager() {
	}
	
	public static ImageManager getInstance() {
		if (instance!=null) return instance;
		synchronized (ImageManager.class) {
			if (instance==null) {
				instance = new ImageManager();
			}
		}
		return instance;
	}
	
	public void initialize(Context context) {
		memCache = new MemCacheImpl(context);
		memCache.mallocSpace();
	}
	
	class UrlView {
		private WeakReference<ImageView> view;
		public UrlView(ImageView imageView) {
			view = new WeakReference<ImageView>(imageView);
		}
	}
	
	private HashMap<String, LinkedList<UrlView>> urlDownloadMap = new HashMap<String, LinkedList<UrlView>>();
	
	public void loadImage(final String url, final ImageView imageView, final int width, final int height, LocalCallBack callBack) {
	        if (url == null) return;
	        
	        String cachekey = CacheKey.getCacheKey(url);
	        if(imageView != null) {
	        	imageView.setImageBitmap(null);
	        }
	        Bitmap bitmap = null;
	        if (memCache != null) {
	            bitmap = memCache.readCache(cachekey);
	        }
	        
	        if (bitmap != null) {
//	        	if(imageView instanceof LoadImageView)
//					((LoadImageView) imageView).updateProgressComplete();
	        	imageView.setImageBitmap(bitmap);
	        	if(callBack != null)
	        		callBack.callBack(url);
	        	return;
	        }
	        
	        removeView(imageView);
	        
	        if(urlDownloadMap.get(url)!=null)
	        {
	        	LogUtil.d("http", "url is downloading ");
	        	urlDownloadMap.get(url).add(new UrlView(imageView));
//	        	if(imageView instanceof LoadImageView)
//					((LoadImageView) imageView).updateProgressBegian();
	        	return;
	        }
	        else
	        {
	        	LogUtil.d("http", "url download started ");
	        	LinkedList<UrlView> list = new LinkedList<UrlView>();
	        	list.add(new UrlView(imageView));
	        	urlDownloadMap.put(url, list);
//	        	if(imageView instanceof LoadImageView)
//					((LoadImageView) imageView).updateProgressBegian();
	        }
	        
	        new ImageDownloadCommand(url, null, width, height, callBack).execute();
	}
	
	private void removeView(ImageView imageView)
	{
		Iterator<Entry<String, LinkedList<UrlView>>> iter = urlDownloadMap.entrySet().iterator();
		while(iter.hasNext()){
			Entry<String, LinkedList<UrlView>> entity = iter.next();
			if(entity.getValue() == null)
				return;
			Iterator<UrlView> listIterator = entity.getValue().iterator();
			while(listIterator.hasNext())
			{
				if(listIterator.next().view.get() == imageView)
				{
					LogUtil.d("http", "imageview is replaced ");
//					if(imageView instanceof LoadImageView)
//						((LoadImageView) imageView).updateProgressComplete();
					listIterator.remove();
				}
			}
		}
	}
	
    private int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
        final int height = options.outHeight;
        final int width = options.outWidth;
        int inSampleSize = 1;

        if (height > reqHeight || width > reqWidth) {
            if (width > height) {
                inSampleSize = Math.round((float) height / (float) reqHeight);
            } else {
                inSampleSize = Math.round((float) width / (float) reqWidth);
            }

            final float totalPixels = width * height;
            final float totalReqPixelsCap = reqWidth * reqHeight * 2;

            while (totalPixels / (inSampleSize * inSampleSize) > totalReqPixelsCap) {
                inSampleSize++;
            }
        }
        return inSampleSize;
    }
    
    private Bitmap decodeSampledBitmapFromResource(String in,int reqWidth, int reqHeight) {
	    // 首先设置 inJustDecodeBounds=true 来检查尺寸
	    final BitmapFactory.Options options = new BitmapFactory.Options();
	    options.inJustDecodeBounds = true;
	    BitmapFactory.decodeFile(in, options);
	    // 计算压缩比例
	    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
	  
	    // 设置inJustDecodeBounds为false
	    options.inJustDecodeBounds = false;
	    
	    Bitmap bitmap = BitmapFactory.decodeFile(in, options);
	    
	    return bitmap;
	}
    
    class ImageDownloadCommand extends SimpleBaseCommand{

    	private String url;
    	private WeakReference<ImageView> view;
    	private int width;
    	private int height;
    	private LocalCallBack callBack;
    	public ImageDownloadCommand(String url,View view, int width, int height, LocalCallBack callBack) {
    		this.url = url;
    		this.view = new WeakReference<ImageView>((ImageView) view);
    		this.width = width;
    		this.height = height;
    		this.callBack = callBack;
    	}
    	
    	@Override
    	public Result go() {
    		Result result = new Result();
    		String requestUrl  = url;
    		try  {
    			LogUtil.d("http", url);
    			
    			if(url.contains("http://")) {
    				HttpCacheItem item = HttpCacheDAO.getInstance().getFileIndexItem(CacheKey.getCacheKey(new URL(requestUrl).getPath()));
    				if(item != null && !item.isTemp() && new File(item.getPath()).exists())
        				requestUrl = item.getPath();
        			else
        				requestUrl = new HttpTemplate().download(url, this).object.toString();	
    			}
    			LogUtil.d("http", requestUrl);
				result.object = decodeSampledBitmapFromResource(requestUrl,width, height);
				
    		} catch(Exception e) {
    			e.printStackTrace();
    		} 
			return result;
    		
    	}
    	

    	@Override
		protected void update(long planSize, long curSize) {
    		if(callBack != null) {
    			callBack.updateProgres(planSize, curSize);
    		}
    		
    		LinkedList<UrlView> list = urlDownloadMap.get(url);
			for(UrlView urlView:list)
			{
				if(urlView.view.get() != null)
				{
					if(urlView.view.get() instanceof LoadImageView)
						((LoadImageView) urlView.view.get()).updateProgress(planSize, curSize);
				}
			}
		}

		@Override
    	public void yes(Result result) {
			try {
				LinkedList<UrlView> list = urlDownloadMap.remove(url);
				for(UrlView urlView:list)
				{
					if(urlView.view.get() != null)
					{
						urlView.view.get().setImageBitmap((Bitmap) result.object);
						if(urlView.view.get() instanceof LoadImageView)
							((LoadImageView) urlView.view.get()).updateProgressComplete();
					}
				}
				if(view != null&&view.get()!= null) {
					view.get().setImageBitmap((Bitmap) result.object);
				}
				
				
				LogUtil.d("http", "图片展示完成");
				memCache.writeCache(CacheKey.getCacheKey(url), (Bitmap)result.object);
				if(callBack != null&&result.object!= null) {
					callBack.callBack(result.object.toString());
				}
			} catch (CacheOutException e) {
				e.printStackTrace();
				Log.d("tag", result.message);
			}
    	}
    	
    	@Override
    	public void no(Result result) {
    		super.no(result);
    		urlDownloadMap.remove(url);
			Log.d("tag", "下载失败");
    	}
    }
    
    public void uploadImage(File file, Context context, LocalCallBack localCallBack) {
		new UploadCommand(file, context, localCallBack).execute();
	}
    
    class UploadCommand extends SimpleBaseCommand{

    	private File file;
    	private LocalCallBack callBack;
    	public UploadCommand(File file,Context context, LocalCallBack callBack) {
    		super(context);
    		this.file = file;
    		this.callBack = callBack;
    	}
    	
    	public UploadCommand(String path, Context context) {
    		super(context);
    		file = new File(path);
    	}
    	
    	@Override
    	public Result go() {
    		return new HttpTemplate().upload(AppConfigContext.TAPLINKER_WEB + "/services/v2/upload" , file, this);
    	}

    	@Override
    	public void yes(Result result) {
    		try {
    			if(callBack != null) {
    				callBack.callBack(result.object);
    				URL url = new URL(AppConfigContext.WEB_DISK_ROOT +result.object.toString());
        			HttpCacheDAO.getInstance().insert(CacheKey.getCacheKey(url.getPath()), file.getPath(), 1, "false");
    			}
    		}catch(Exception e){
    			
    		}
    	}

    	@Override
    	public void no(Result result) {
    		super.no(result);
    		callBack.no();
    	}
    	
    	@Override
    	protected void update(long planSize, long curSize) {
    		callBack.updateProgres(planSize, curSize);
    	}
    	
    }
    
	public interface LocalCallBack {
		public void callBack(Object obj);
		public void updateProgres(long planSize, long curSize);
		public void no();
	}
}
